#include "NpkCoder.h"
#include "Handlers/HandlerManager.h"

NpkCoder::NpkCoder(QObject *parent)
    : QObject(parent)
    , m_usingDataStreamPtr(nullptr)
    , m_handlerMg(new HandlerManager(parent))
{
}

void NpkCoder::Load(const QString &path)
{
    m_albumList.clear();

    QFile file(path);
    if (!file.exists()) {
        qCritical() << Q_FUNC_INFO << path << "not exists!";
        return;
    }
    if (!file.open(QIODevice::OpenModeFlag::ReadOnly)) {
        qCritical() << Q_FUNC_INFO << path << "open failed!";
        return;
    }
    m_oriBa = file.readAll();
    file.close();
    if (m_usingDataStreamPtr) {
        delete m_usingDataStreamPtr;
        m_usingDataStreamPtr = nullptr;
    }
    m_usingDataStreamPtr = new QDataStream(m_oriBa);

    readNpk();
}

const QList<Album> &NpkCoder::GetAlbumList()
{
    return m_albumList;
}

QImage NpkCoder::GetSpriteImg(const Album &album, const SpriteStruct &sprite)
{
    Handler *handler = m_handlerMg->GetHandler(album.Version);
    return handler->GetSpriteImg(album, sprite);
}

void NpkCoder::readNpk()
{
    const QByteArray &flag = ReadFromDataStream(m_usingDataStreamPtr, 15);
    if (flag == NPK_FlAG) {
        //当文件是NPK时
        ReadByteFromDataStream(m_usingDataStreamPtr);
        const QList<Album> &albumList = readInfo();
        m_albumList.append(albumList);
    }
    for (Album &album : m_albumList) {
        readImg(album);
    }
}

QString readPath(QDataStream *streamPtr)
{
    const QByteArray &ba = ReadFromDataStream(streamPtr, 256);

    QString path;
    for (int i = 0; i < 256; i++) {
        char c = ba.at(i);
        char xorC = c ^ DecodeKey[i];
        if (xorC == '\0') {
            break;
        }
        path += xorC;
    }

    return path;
}


QList<Album> NpkCoder::readInfo()
{
    QList<Album> retList;
    int count = ReadInt(m_usingDataStreamPtr);
    for (int i = 0; i < count; i++) {
        Album album;
        album.Offset = ReadInt(m_usingDataStreamPtr);
        album.Length = ReadInt(m_usingDataStreamPtr);

        album.Path = readPath(m_usingDataStreamPtr);
        retList.append(album);
    }
    return retList;
}

void NpkCoder::readImg(Album &album)
{
    QByteArray ba = m_oriBa.mid(album.Offset, album.Length);
    QDataStream stream(ba);

    QString albumFlag = ReadFromDataStream(&stream, IMG_FLAG.length());
    if (albumFlag == IMG_FLAG) {
        ReadByteFromDataStream(&stream);
        album.IndexLength = ReadLongLong(&stream);
        album.Version = ImgVersionEnum(ReadInt(&stream));
        album.Count = ReadInt(&stream);
    }
    if (album.Version == ImgVersionEnum::Other) {
        albumFlag = ReadFromDataStream(&stream, IMG_FLAG.length());
        if (albumFlag == IMAGE_FLAG) {
            album.Version = ImgVersionEnum::Ver1;

            album.Path = "Ver1 Image Is Not Support";
            qCritical() << Q_FUNC_INFO << "up to now, not support Ver1 image!";
            return;
        }
    }

    qDebug() << Q_FUNC_INFO << "album version:" << album.Version;
    Handler *handler = m_handlerMg->GetHandler(album.Version);
    handler->GetSpriteListFromDataStream(album, &stream);
}
